﻿using MultiDAQ_Analysis.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MultiDAQ_Analysis.View
{
    public partial class UcUdpTool : UserControl
    {
        private UdpClient udpClient;
        private volatile bool listening = false;
        private int sendCount = 0;
        private volatile int parsedPointCount = 0;

        // 优化后的线程数量配置
        private int receiveThreadCount = 4;
        private int parseThreadCount = 8;

        // 高性能优化：专用接收线程 + 多个处理线程
        private Thread receiveThread;
        private Thread[] parseThreads;
        private Thread uiUpdateThread;

        // 高性能缓冲区
        private ConcurrentQueue<UdpPacket> receiveQueue = new ConcurrentQueue<UdpPacket>();
        private ConcurrentQueue<VoltagePoint> voltageQueue = new ConcurrentQueue<VoltagePoint>();

        // 批量处理缓冲区
        private List<VoltagePoint> parsedDataBuffer = new List<VoltagePoint>();
        private readonly object bufferLock = new object();
        private const int BUFFER_SIZE = 100000;
        private const int UI_UPDATE_BATCH_SIZE = 1000;

        // 性能统计 - 修复volatile long问题
        private long totalBytesReceived = 0;
        private long totalPacketsReceived = 0;
        private long totalSentPackets = 0;
        private long errorCount = 0;
        private DateTime performanceStartTime;
        private DateTime fileSendStartTime;
        private System.Threading.Timer performanceTimer;

        // 数据解析相关
        private volatile bool enableDataParsing = false;
        private List<VoltagePoint> parsedData = new List<VoltagePoint>();
        private const int MAX_PARSED_DATA = 10000000;


        // 文件发送模拟相关
        private bool fileSending = false;
        private Thread fileSendThread;
        private CancellationTokenSource fileSendCancelTokenSource;
        private int finalBatchCount = 0;

        public void TestSendPerformance()
        {
            byte[] testData = new byte[10 * 1024 * 1024];
            new Random().NextBytes(testData);

            string testFile = Path.GetTempFileName();
            File.WriteAllBytes(testFile, testData);

            AppendLogThreadSafe($"[性能测试] 创建10MB测试文件: {testFile}", Color.Blue);
            AppendLogThreadSafe("[性能测试] 请设置发送间隔为0，然后开始文件发送测试", Color.Blue);

            txtFilePath.Text = testFile;
            lblFileInfo.Text = $"文件大小: {testData.Length} 字节 ({testData.Length / 1024.0 / 1024.0:F1} MB)";
        }

        public UcUdpTool()
        {
            InitializeComponent();
            InitEvent();
            UpdateChannelMaskLabel();
            InitializePerformanceTimer();

            AppendLogThreadSafe($"[优化线程配置] 接收线程: 1(专用), 解析线程: {parseThreadCount}", Color.Blue);
            AppendLogThreadSafe("[性能提示] 要获得最佳发送性能，请将发送间隔设置为0", Color.Green);
            TestSendPerformance();
        }

    

        private void InitializePerformanceTimer()
        {
            performanceTimer = new System.Threading.Timer(UpdatePerformanceStats, null, 1000, 1000);
        }

 
        #region 高性能UDP接收和处理

        private void BtnStartListen_Click(object sender, EventArgs e)
        {
            try
            {
                int listenPort = int.Parse(txtListenPort.Text.Trim());

                udpClient = new UdpClient(listenPort);
                udpClient.Client.ReceiveBufferSize = 64 * 1024 * 1024;
                udpClient.Client.SendBufferSize = 8 * 1024 * 1024;

                listening = true;
                performanceStartTime = DateTime.Now;
                totalBytesReceived = 0;
                totalPacketsReceived = 0;
                totalSentPackets = 0;
                parsedPointCount = 0;
                errorCount = 0;

                while (receiveQueue.TryDequeue(out _)) { }
                while (voltageQueue.TryDequeue(out _)) { }

                receiveThread = new Thread(HighPerformanceReceiveLoop)
                {
                    IsBackground = true,
                    Name = "UdpReceiver-Main",
                    Priority = ThreadPriority.Highest
                };
                receiveThread.Start();

                if (enableDataParsing)
                {
                    StartParseThreads();
                }

                StartUIUpdateThread();

                //AppendLogThreadSafe($"[高性能监听] 已启动，端口：{listenPort}，专用接收线程：1，解析线程：{(enableDataParsing ? parseThreadCount : 0)}", Color.Green);
                btnStartListen.Enabled = false;
                btnStopListen.Enabled = true;
            }
            catch (Exception ex)
            {
                AppendLogThreadSafe("[监听错误] " + ex.Message, Color.Red);
            }
        }

        private void HighPerformanceReceiveLoop()
        {
            var localEP = new IPEndPoint(IPAddress.Any, 0);
            long localReceivedCount = 0;
            long localErrorCount = 0;

            var bufferPool = new ConcurrentBag<byte[]>();
            const int POOL_SIZE = 1000;

            for (int i = 0; i < POOL_SIZE; i++)
            {
                bufferPool.Add(new byte[65507]);
            }

            AppendLogThreadSafe($"[接收线程] 已启动，缓冲区池大小: {POOL_SIZE}", Color.Gray);

            // 修复：控制日志频率
            var lastLogTime = DateTime.Now;
            const int LOG_INTERVAL_SECONDS = 5; // 每5秒最多输出一次
            const long REPORT_THRESHOLD = 500000; // 每50万个包才考虑输出日志

            while (listening)
            {
                try
                {
                    byte[] receivedData = udpClient.Receive(ref localEP);

                    if (receivedData == null || receivedData.Length == 0)
                        continue;

                    localReceivedCount++;
                    Interlocked.Add(ref totalBytesReceived, receivedData.Length);
                    Interlocked.Increment(ref totalPacketsReceived);

                    if (!bufferPool.TryTake(out byte[] buffer))
                    {
                        buffer = new byte[65507];
                    }

                    int dataLength = Math.Min(receivedData.Length, buffer.Length);
                    Buffer.BlockCopy(receivedData, 0, buffer, 0, dataLength);

                    var udpPacket = new UdpPacket
                    {
                        Data = buffer,
                        DataLength = dataLength,
                        RemoteEndPoint = localEP,
                        Timestamp = DateTime.Now
                    };

                    receiveQueue.Enqueue(udpPacket);

                    if (receiveQueue.Count > 500000)
                    {
                        int discardCount = 0;
                        while (receiveQueue.Count > 400000 && receiveQueue.TryDequeue(out UdpPacket discarded))
                        {
                            bufferPool.Add(discarded.Data);
                            discardCount++;
                        }

                        Interlocked.Add(ref errorCount, discardCount);
                        if (discardCount > 0)
                        {
                            // 队列溢出是重要信息，保留但降低频率
                            AppendLogThreadSafe($"[队列管理] 丢弃 {discardCount} 个包，当前队列: {receiveQueue.Count}", Color.Orange);
                        }
                    }

                    // 修复：严格控制日志输出
                    if (localReceivedCount % REPORT_THRESHOLD == 0)
                    {
                        var now = DateTime.Now;
                        if ((now - lastLogTime).TotalSeconds >= LOG_INTERVAL_SECONDS)
                        {
                            AppendLogThreadSafe($"[接收线程] 累计接收: {localReceivedCount:N0}, 队列深度: {receiveQueue.Count}", Color.Gray);
                            lastLogTime = now;
                        }
                    }
                }
                catch (Exception ex)
                {
                    localErrorCount++;
                    Interlocked.Increment(ref errorCount);

                    if (listening && localErrorCount % 1000 == 1)
                    {
                        AppendLogThreadSafe($"[接收错误] {ex.Message} (已发生{localErrorCount}次)", Color.Red);
                    }
                }
            }

            AppendLogThreadSafe($"[接收线程结束] 共接收: {localReceivedCount:N0} 包, 错误: {localErrorCount}", Color.Gray);
        }

        private void StartParseThreads()
        {
            parseThreads = new Thread[parseThreadCount];
            for (int i = 0; i < parseThreadCount; i++)
            {
                parseThreads[i] = new Thread(HighPerformanceParseLoop)
                {
                    IsBackground = true,
                    Name = $"DataParser-{i}",
                    Priority = ThreadPriority.AboveNormal
                };
                parseThreads[i].Start();
            }
        }

        // 修改解析线程，只打印第一条和最后一条，并完善统计
        private void HighPerformanceParseLoop()
        {
            const int ADC_DATA_WIDTH = 16;
            const double VOL_RANGE = 5.0;
            const int SAMPLE_RATE = 2000000;
            double LSB = VOL_RANGE * 2 / Math.Pow(2, ADC_DATA_WIDTH);

            var localBatch = new List<VoltagePoint>(5000);
            long localErrorCount = 0;
            long localProcessedCount = 0;

            // 解析统计变量
            bool firstDataParsed = false;
            DateTime parseStartTime = DateTime.MinValue;
            DateTime lastParseTime = DateTime.MinValue;
            VoltagePoint firstVoltagePoint = default;
            VoltagePoint lastVoltagePoint = default;
            long totalParsedPoints = 0;

            var lastLogTime = DateTime.Now;
            const int LOG_INTERVAL_SECONDS = 10;
            const long REPORT_THRESHOLD = 1000000;

            while (listening || !receiveQueue.IsEmpty)
            {
                try
                {
                    for (int i = 0; i < 500 && receiveQueue.TryDequeue(out UdpPacket packet); i++)
                    {
                        localProcessedCount++;

                        if (IsProtocolFrame(packet.Data, packet.DataLength))
                        {
                            ProcessProtocolFrameAsync(packet);
                            continue;
                        }

                        if (!enableDataParsing || packet.DataLength < 2)
                            continue;

                        // 记录解析开始时间
                        if (!firstDataParsed)
                        {
                            parseStartTime = DateTime.Now;
                            firstDataParsed = true;
                        }

                        lastParseTime = DateTime.Now;

                        int batchSizeBefore = localBatch.Count;
                        ParseADCDataFast(packet.Data, packet.DataLength, packet.RemoteEndPoint, packet.Timestamp, localBatch, LSB, SAMPLE_RATE);

                        // 只记录第一个数据点
                        if (batchSizeBefore == 0 && localBatch.Count > 0 && firstVoltagePoint.Equals(default(VoltagePoint)))
                        {
                            firstVoltagePoint = localBatch[0];
                            AppendLogThreadSafe($"[第一个ADC数据点] 时间: {firstVoltagePoint.Timestamp:HH:mm:ss.fff} | 电压: {firstVoltagePoint.Voltage:F4}V | 来源: {firstVoltagePoint.Source}", Color.Purple);
                        }

                        // 持续更新最后一个数据点（但不打印）
                        if (localBatch.Count > 0)
                        {
                            lastVoltagePoint = localBatch[localBatch.Count - 1];
                        }
                    }

                    if (localBatch.Count > 0)
                    {
                        foreach (var point in localBatch)
                        {
                            voltageQueue.Enqueue(point);
                        }

                        Interlocked.Add(ref parsedPointCount, localBatch.Count);
                        totalParsedPoints += localBatch.Count;
                        localBatch.Clear();

                        while (voltageQueue.Count > MAX_PARSED_DATA)
                        {
                            voltageQueue.TryDequeue(out _);
                        }
                    }

                    if (receiveQueue.IsEmpty)
                    {
                        Thread.Sleep(1);
                    }

                    // 定期输出统计信息
                    if (localProcessedCount % REPORT_THRESHOLD == 0 && firstDataParsed)
                    {
                        var now = DateTime.Now;
                        if ((now - lastLogTime).TotalSeconds >= LOG_INTERVAL_SECONDS)
                        {
                            var parseElapsed = now - parseStartTime;
                            double packetProcessingRate = localProcessedCount / parseElapsed.TotalSeconds;
                            double pointParsingRate = totalParsedPoints / parseElapsed.TotalSeconds;
                            double avgPointsPerPacket = totalParsedPoints > 0 ? (double)totalParsedPoints / localProcessedCount : 0;

                            AppendLogThreadSafe($"[解析统计] 线程{Thread.CurrentThread.Name} | 已处理包: {localProcessedCount:N0} | 已解析点: {totalParsedPoints:N0} | 平均点/包: {avgPointsPerPacket:F1}", Color.Gray);
                            AppendLogThreadSafe($"[解析速率] 包处理: {packetProcessingRate:F0} pps | 点解析: {pointParsingRate:F0} 点/秒 | 累计耗时: {parseElapsed.TotalSeconds:F1}s", Color.Gray);
                            lastLogTime = now;
                        }
                    }
                }
                catch (Exception ex)
                {
                    localErrorCount++;
                    Interlocked.Increment(ref errorCount);

                    if (localErrorCount % 1000 == 1)
                    {
                        AppendLogThreadSafe($"[解析错误] 线程{Thread.CurrentThread.Name}: {ex.Message}", Color.Red);
                    }
                    Thread.Sleep(10);
                }
            }

            // 线程结束时打印最后一个数据点和最终统计
            if (firstDataParsed)
            {
                var totalParseTime = lastParseTime - parseStartTime;
                double finalPacketRate = localProcessedCount / totalParseTime.TotalSeconds;
                double finalPointRate = totalParsedPoints / totalParseTime.TotalSeconds;
                double finalAvgPointsPerPacket = totalParsedPoints > 0 ? (double)totalParsedPoints / localProcessedCount : 0;

                AppendLogThreadSafe($"[最后一个ADC数据点] 时间: {lastVoltagePoint.Timestamp:HH:mm:ss.fff} | 电压: {lastVoltagePoint.Voltage:F4}V | 来源: {lastVoltagePoint.Source}", Color.Purple);
                AppendLogThreadSafe($"[解析线程完成] {Thread.CurrentThread.Name} | 总处理包: {localProcessedCount:N0} | 总解析点: {totalParsedPoints:N0} | 错误: {localErrorCount}", Color.Blue);
                AppendLogThreadSafe($"[最终解析速率] 包处理: {finalPacketRate:F0} pps | 点解析: {finalPointRate:F0} 点/秒 | 平均点/包: {finalAvgPointsPerPacket:F1} | 总耗时: {totalParseTime.TotalSeconds:F3}s", Color.Blue);
            }
            else
            {
                AppendLogThreadSafe($"[解析线程结束] {Thread.CurrentThread.Name} | 未处理任何ADC数据 | 总处理包: {localProcessedCount:N0} | 错误: {localErrorCount}", Color.Gray);
            }
        }

        // 同时优化性能统计显示，增加更详细的接收和解析速率信息
        private void UpdatePerformanceStats(object state)
        {
            if (listening && performanceStartTime != DateTime.MinValue)
            {
                var elapsed = DateTime.Now - performanceStartTime;
                if (elapsed.TotalSeconds > 0)
                {
                    double mbps = (totalBytesReceived / 1024.0 / 1024.0) / elapsed.TotalSeconds;
                    double pps = totalPacketsReceived / elapsed.TotalSeconds;
                    double parsePointsPerSecond = parsedPointCount / elapsed.TotalSeconds;

                    if (InvokeRequired)
                    {
                        BeginInvoke(new Action(() =>
                        {
                            long sent = totalSentPackets;
                            long received = totalPacketsReceived;
                            long lost = sent - received;
                            double lossRate = sent > 0 ? (double)lost / sent * 100 : 0;

                            // 更详细的接收统计
                            lblReceiveCount.Text = $"发送: {sent:N0} | 接收: {received:N0} | 丢失: {lost:N0} ({lossRate:F3}%) | 速率: {mbps:F2}MB/s {pps:F0}pps | R队列: {receiveQueue.Count} | 错误: {errorCount} | 耗时: {elapsed.TotalSeconds:F1}s";

                            if (enableDataParsing)
                            {
                                double avgPointsPerPacket = received > 0 ? (double)parsedPointCount / received : 0;
                                lblParsedDataCount.Text = $"解析数据点: {parsedPointCount:N0} | V队列: {voltageQueue.Count} | 解析速率: {parsePointsPerSecond:F0}点/s | 平均点/包: {avgPointsPerPacket:F1} | 解析线程: {parseThreadCount}";
                            }
                            else
                            {
                                lblParsedDataCount.Text = $"解析: 未启用 | 解析线程: 0";
                            }
                        }));
                    }
                }
            }
        }

        // 修改停止监听方法，添加最终的详细统计
        private void BtnStopListen_Click(object sender, EventArgs e)
        {
            listening = false;

            AppendLogThreadSafe("[停止监听] 正在停止接收和解析线程...", Color.Orange);

            // 记录停止时间
            DateTime stopTime = DateTime.Now;
            var totalElapsed = stopTime - performanceStartTime;

            // 等待接收线程结束
            if (receiveThread != null && receiveThread.IsAlive)
            {
                bool stopped = receiveThread.Join(3000);
                if (!stopped)
                {
                    AppendLogThreadSafe($"[警告] 接收线程未能在3秒内正常结束", Color.Orange);
                }
            }

            // 等待解析线程结束
            int stoppedParseThreads = 0;
            if (parseThreads != null)
            {
                for (int i = 0; i < parseThreads.Length; i++)
                {
                    if (parseThreads[i] != null && parseThreads[i].IsAlive)
                    {
                        bool stopped = parseThreads[i].Join(2000);
                        if (stopped)
                        {
                            stoppedParseThreads++;
                        }
                        else
                        {
                            AppendLogThreadSafe($"[警告] 解析线程 {parseThreads[i].Name} 未能正常结束", Color.Orange);
                        }
                    }
                }
            }

            if (uiUpdateThread != null && uiUpdateThread.IsAlive)
            {
                uiUpdateThread.Join(1000);
            }

            udpClient?.Close();
            udpClient = null;

            receiveThread = null;
            parseThreads = null;
            uiUpdateThread = null;

            // 最终详细统计报告
            long finalSent = totalSentPackets;
            long finalReceived = totalPacketsReceived;
            long finalParsed = parsedPointCount;
            double finalLossRate = finalSent > 0 ? (double)(finalSent - finalReceived) / finalSent * 100 : 0;

            double totalMB = totalBytesReceived / 1024.0 / 1024.0;
            double avgReceiveSpeedMBps = totalMB / totalElapsed.TotalSeconds;
            double avgPacketRate = finalReceived / totalElapsed.TotalSeconds;
            double avgParseRate = finalParsed / totalElapsed.TotalSeconds;
            double avgPointsPerPacket = finalReceived > 0 ? (double)finalParsed / finalReceived : 0;

            AppendLogThreadSafe($"[监听已停止] 解析线程停止: {stoppedParseThreads}/{parseThreadCount}", Color.Black);
            AppendLogThreadSafe(new string('=', 80), Color.Magenta);
            AppendLogThreadSafe($"[最终统计报告]", Color.Magenta);
            AppendLogThreadSafe($"[包统计] 发送: {finalSent:N0} | 接收: {finalReceived:N0} | 丢失: {finalSent - finalReceived:N0} | 丢包率: {finalLossRate:F3}%", Color.Magenta);
            AppendLogThreadSafe($"[数据统计] 总接收: {totalMB:F2} MB | 解析点数: {finalParsed:N0} | 平均点/包: {avgPointsPerPacket:F1}", Color.Magenta);
            AppendLogThreadSafe($"[性能统计] 接收速率: {avgReceiveSpeedMBps:F2} MB/s | 包速率: {avgPacketRate:F0} pps | 解析速率: {avgParseRate:F0} 点/秒", Color.Magenta);
            AppendLogThreadSafe($"[时间统计] 总运行时间: {totalElapsed.TotalSeconds:F3} 秒 ({totalElapsed.TotalMinutes:F2} 分钟)", Color.Magenta);
            AppendLogThreadSafe(new string('=', 80), Color.Magenta);

            btnStartListen.Enabled = true;
            btnStopListen.Enabled = false;
        }

        private void ParseADCDataFast(byte[] rawData, int dataLength, IPEndPoint remoteEP, DateTime timestamp,
            List<VoltagePoint> batch, double LSB, int sampleRate)
        {
            const int ADC_DATA_WIDTH = 16;
            double sampleInterval = 1000000.0 / sampleRate;

            for (int i = 0; i < dataLength - 1; i += 2)
            {
                int adcCode = rawData[i] | (rawData[i + 1] << 8);

                if (adcCode > (1 << (ADC_DATA_WIDTH - 1)))
                {
                    adcCode -= (1 << ADC_DATA_WIDTH);
                }

                double voltage = adcCode * LSB - LSB / 2;
                double sampleTimeUs = sampleInterval * (i / 2 + 1);
                DateTime sampleTime = timestamp.AddTicks((long)(sampleTimeUs * 10));

                batch.Add(new VoltagePoint(sampleTime, voltage, i / 2, remoteEP.ToString()));
            }
        }

        private void StartUIUpdateThread()
        {
            uiUpdateThread = new Thread(UIUpdateLoop)
            {
                IsBackground = true,
                Name = "UIUpdater",
                Priority = ThreadPriority.BelowNormal
            };
            uiUpdateThread.Start();
        }

        private void UIUpdateLoop()
        {
            var displayBatch = new List<VoltagePoint>(UI_UPDATE_BATCH_SIZE);
            int updateCounter = 0;
            var lastLogTime = DateTime.Now;

            while (listening || !voltageQueue.IsEmpty)
            {
                try
                {
                    for (int i = 0; i < UI_UPDATE_BATCH_SIZE && voltageQueue.TryDequeue(out VoltagePoint point); i++)
                    {
                        displayBatch.Add(point);
                    }

                    if (displayBatch.Count > 0)
                    {
                        lock (bufferLock)
                        {
                            parsedDataBuffer.AddRange(displayBatch);

                            while (parsedDataBuffer.Count > BUFFER_SIZE)
                            {
                                parsedDataBuffer.RemoveAt(0);
                            }
                        }

                        updateCounter++;
                        //if (updateCounter % 50 == 0)
                        //{
                        //    UpdateParsedDataDisplayAsync(displayBatch.Take(5).ToList());
                        //}

                        displayBatch.Clear();
                    }
                    else
                    {
                        Thread.Sleep(20);
                    }
                }
                catch (Exception ex)
                {
                    // 修复：UI错误日志也要控制频率
                    var now = DateTime.Now;
                    if ((now - lastLogTime).TotalSeconds >= 30) // 30秒才输出一次UI错误
                    {
                        AppendLogThreadSafe($"[UI更新错误] {ex.Message}", Color.Red);
                        lastLogTime = now;
                    }
                    Thread.Sleep(100);
                }
            }
        }



        #endregion



        #region 数据解析功能增强

        private void ChkEnableParsing_CheckedChanged(object sender, EventArgs e)
        {
            enableDataParsing = chkEnableParsing.Checked;

            if (enableDataParsing)
            {
                AppendLogThreadSafe($"[数据解析] 已启用高性能ADC数据解析 ({parseThreadCount} 个解析线程)", Color.Green);
                if (listening && parseThreads == null)
                {
                    StartParseThreads();
                }
            }
            else
            {
                AppendLogThreadSafe("[数据解析] 已禁用数据解析", Color.Gray);
            }

            UpdateParsingStatusLabel();
        }

        private void BtnClearParsedData_Click(object sender, EventArgs e)
        {
            lock (bufferLock)
            {
                parsedDataBuffer.Clear();
            }

            while (voltageQueue.TryDequeue(out _)) { }

            lstParsedData.Items.Clear();
            parsedPointCount = 0;
            UpdateParsedDataCountLabel();
            AppendLogThreadSafe("[数据解析] 已清空解析数据", Color.Blue);
        }

        private void UpdateParsingStatusLabel()
        {
            if (lblParsingStatus.InvokeRequired)
            {
                lblParsingStatus.BeginInvoke(new Action(UpdateParsingStatusLabel));
                return;
            }

            lblParsingStatus.Text = enableDataParsing ? $"解析状态: 启用({parseThreadCount}线程)" : "解析状态: 禁用";
            lblParsingStatus.ForeColor = enableDataParsing ? Color.Green : Color.Gray;
        }

        private void UpdateParsedDataCountLabel()
        {
            if (lblParsedDataCount.InvokeRequired)
            {
                lblParsedDataCount.BeginInvoke(new Action(UpdateParsedDataCountLabel));
                return;
            }

            lblParsedDataCount.Text = $"解析数据点: {parsedPointCount}";
        }

        #endregion

        #region 异步UI更新和辅助方法

        // 添加日志速率限制
        private readonly Dictionary<string, DateTime> logThrottle = new Dictionary<string, DateTime>();
        private readonly object logThrottleLock = new object();

        private void AppendLogThreadSafeAsync(string text, Color color = default)
        {
            // 对于高频日志，使用节流机制
            if (text.Contains("处理:") || text.Contains("累计"))
            {
                string key = text.Substring(0, Math.Min(20, text.Length)); // 使用前20个字符作为key
                lock (logThrottleLock)
                {
                    if (logThrottle.TryGetValue(key, out DateTime lastTime))
                    {
                        if ((DateTime.Now - lastTime).TotalSeconds < 3) // 3秒内相同类型日志只输出一次
                        {
                            return;
                        }
                    }
                    logThrottle[key] = DateTime.Now;
                }
            }

            // 使用线程池而不是Task.Run，减少线程创建开销
            ThreadPool.QueueUserWorkItem(_ => AppendLogThreadSafe(text, color));
        }


        //private void UpdateParsedDataDisplayAsync(List<VoltagePoint> newPoints)
        //{
        //    if (InvokeRequired)
        //    {
        //        BeginInvoke(new Action<List<VoltagePoint>>(UpdateParsedDataDisplaySync), newPoints);
        //        return;
        //    }
        //    UpdateParsedDataDisplaySync(newPoints);
        //}

        //private void UpdateParsedDataDisplaySync(List<VoltagePoint> newPoints)
        //{
        //    try
        //    {
        //        foreach (var point in newPoints)
        //        {
        //            string displayText = $"[{point.SampleIndex:D6}] {point.Timestamp:HH:mm:ss.fff} - " +
        //                               $"{point.Voltage:F4}V";
        //            lstParsedData.Items.Add(displayText);
        //        }

        //        while (lstParsedData.Items.Count > 100)
        //        {
        //            lstParsedData.Items.RemoveAt(0);
        //        }

        //        if (lstParsedData.Items.Count > 0)
        //        {
        //            lstParsedData.TopIndex = lstParsedData.Items.Count - 1;
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        // 忽略UI更新错误
        //    }
        //}

        private void ProcessProtocolFrameAsync(UdpPacket packet)
        {
            Task.Run(() =>
            {
                try
                {
                    if (packet.DataLength >= 8)
                    {
                        byte reg = packet.Data[2];
                        uint data = (uint)(packet.Data[3] << 24) | (uint)(packet.Data[4] << 16) |
                                   (uint)(packet.Data[5] << 8) | (uint)packet.Data[6];

                        AppendLogThreadSafeAsync(
                            $"[协议帧] ← {packet.RemoteEndPoint} - REG=0x{reg:X2}, DATA=0x{data:X8}",
                            Color.Green);
                    }
                }
                catch (Exception ex)
                {
                    AppendLogThreadSafeAsync($"[协议帧解析错误] {ex.Message}", Color.Red);
                }
            });
        }

        private static bool IsProtocolFrame(byte[] bytes, int length)
        {
            return bytes != null && length >= 8 &&
                   bytes[0] == 0x55 && bytes[1] == 0xA5 && bytes[7] == 0xF0;
        }

        #endregion

        #region 文件发送功能

        private void BtnBrowseFile_Click(object sender, EventArgs e)
        {
            finalBatchCount = 0;

            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "Log files (*.log)|*.log|Binary files (*.bin)|*.bin|All files (*.*)|*.*";
                openFileDialog.Title = "选择要发送的数据文件";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    txtFilePath.Text = openFileDialog.FileName;

                    try
                    {
                        var fileInfo = new FileInfo(openFileDialog.FileName);
                        lblFileInfo.Text = $"文件大小: {fileInfo.Length} 字节 ({fileInfo.Length / 1024.0:F1} KB)";

                        AppendLogThreadSafe($"[文件选择] 已选择文件: {fileInfo.Name}, 大小: {fileInfo.Length} 字节", Color.Blue);
                    }
                    catch (Exception ex)
                    {
                        AppendLogThreadSafe($"[文件选择错误] {ex.Message}", Color.Red);
                    }
                }
            }
        }

        private void BtnStartFileSend_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtFilePath.Text) || !File.Exists(txtFilePath.Text))
            {
                MessageBox.Show("请选择有效的文件路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (fileSending)
            {
                return;
            }

            try
            {
                btnStartFileSend.Enabled = false;
                btnStopFileSend.Enabled = true;
                fileSending = true;
                fileSendCancelTokenSource = new CancellationTokenSource();

                string targetIP = txtSendIP.Text.Trim();
                int targetPort = int.Parse(txtSendPort.Text.Trim());
                int packetSize = (int)nudPacketSize.Value;
                int interval = (int)nudSendInterval.Value;

                AppendLogThreadSafe($"[文件发送] 开始发送文件到 {targetIP}:{targetPort}", Color.Green);

                fileSendThread = new Thread(() => SendFileLoop(txtFilePath.Text, targetIP, targetPort, packetSize, interval, fileSendCancelTokenSource.Token))
                {
                    IsBackground = true
                };
                fileSendThread.Start();
            }
            catch (Exception ex)
            {
                AppendLogThreadSafe($"[文件发送错误] {ex.Message}", Color.Red);
                ResetFileSendUI();
            }
        }

        private void BtnStopFileSend_Click(object sender, EventArgs e)
        {
            StopFileSending();
        }

        private void StopFileSending()
        {
            fileSending = false;
            fileSendCancelTokenSource?.Cancel();

            if (fileSendThread != null && fileSendThread.IsAlive)
            {
                fileSendThread.Join(1000);
            }

            ResetFileSendUI();
            AppendLogThreadSafe("[文件发送] 已停止", Color.Black);
        }

        private void ResetFileSendUI()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(ResetFileSendUI));
                return;
            }

            btnStartFileSend.Enabled = true;
            btnStopFileSend.Enabled = false;
            progressBarFileSend.Value = 0;
            lblSendProgress.Text = "发送进度: 0%";
        }

        private void SendFileLoop(string filePath, string targetIP, int targetPort, int packetSize, int interval, CancellationToken cancellationToken)
        {
            fileSendStartTime = DateTime.Now;

            try
            {
                byte[] fileData = File.ReadAllBytes(filePath);
                int totalPackets = (int)Math.Ceiling((double)fileData.Length / packetSize);
                int sentPackets = 0;

                UpdateProgressThreadSafe(0, totalPackets);

                using (var udpSender = new UdpClient())
                {
                    udpSender.Client.SendBufferSize = 16 * 1024 * 1024;
                    udpSender.Connect(targetIP, targetPort);

                    if (interval == 0)
                    {
                        SendBurstMode(fileData, udpSender, packetSize, totalPackets, ref sentPackets, cancellationToken);
                    }
                    else
                    {
                        SendThrottledMode(fileData, udpSender, packetSize, totalPackets, ref sentPackets, interval, cancellationToken);
                    }
                }

                var sendDuration = DateTime.Now - fileSendStartTime;
                if (!cancellationToken.IsCancellationRequested)
                {
                    double totalMB = fileData.Length / 1024.0 / 1024.0;
                    double sendSpeedMBps = totalMB / sendDuration.TotalSeconds;

                    AppendLogThreadSafe($"[文件发送完成] 共发送 {sentPackets} 个数据包", Color.Green);
                    AppendLogThreadSafe($"[发送统计] 文件: {totalMB:F2} MB | 耗时: {sendDuration.TotalSeconds:F2}s | 速度: {sendSpeedMBps:F2} MB/s", Color.Blue);
                }
            }
            catch (OperationCanceledException)
            {
                var sendDuration = DateTime.Now - fileSendStartTime;
                AppendLogThreadSafe($"[文件发送] 用户取消 - 耗时: {sendDuration.TotalSeconds:F2}s", Color.Orange);
            }
            catch (Exception ex)
            {
                var sendDuration = DateTime.Now - fileSendStartTime;
                AppendLogThreadSafe($"[文件发送错误] {ex.Message} - 耗时: {sendDuration.TotalSeconds:F2}s", Color.Red);
            }
            finally
            {
                fileSending = false;
                ResetFileSendUI();
            }
        }

        private void SendBurstMode(byte[] fileData, UdpClient udpSender, int packetSize, int totalPackets, ref int sentPackets, CancellationToken cancellationToken)
        {
            const int BATCH_SIZE = 10000;
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            byte[] packet = new byte[packetSize];

            for (int i = 0; i < fileData.Length && !cancellationToken.IsCancellationRequested; i += packetSize)
            {
                int currentPacketSize = Math.Min(packetSize, fileData.Length - i);

                try
                {
                    if (currentPacketSize == packetSize)
                    {
                        Buffer.BlockCopy(fileData, i, packet, 0, currentPacketSize);
                        udpSender.Send(packet, currentPacketSize);
                    }
                    else
                    {
                        byte[] lastPacket = new byte[currentPacketSize];
                        Buffer.BlockCopy(fileData, i, lastPacket, 0, currentPacketSize);
                        udpSender.Send(lastPacket, currentPacketSize);
                    }

                    sentPackets++;
                    sendCount++;
                    Interlocked.Increment(ref totalSentPackets);
                }
                catch (Exception ex)
                {
                    AppendLogThreadSafeAsync($"[发送失败] 包 {sentPackets}: {ex.Message}", Color.Red);
                    continue;
                }

                if (sentPackets % BATCH_SIZE == 0 || sentPackets == totalPackets)
                {
                    UpdateSendCountLabel();
                    UpdateProgressThreadSafe(sentPackets, totalPackets);

                    if (sentPackets % (BATCH_SIZE * 5) == 0 || sentPackets == totalPackets)
                    {
                        double elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
                        double mbps = (sentPackets * packetSize / 1024.0 / 1024.0) / elapsedSeconds;
                        double pps = sentPackets / elapsedSeconds;

                        long currentReceived = totalPacketsReceived;
                        double lossRate = sentPackets > 0 ? (double)(sentPackets - currentReceived) / sentPackets * 100 : 0;

                        AppendLogThreadSafe(
                            $"[极速发送] {sentPackets}/{totalPackets} | 已收: {currentReceived} | " +
                            $"丢包率: {lossRate:F2}% | {mbps:F1} MB/s, {pps:F0} pps",
                            Color.DarkCyan);
                    }
                }

                if (sentPackets % 10000 == 0 && cancellationToken.IsCancellationRequested)
                    break;
            }
        }

        private void SendThrottledMode(byte[] fileData, UdpClient udpSender, int packetSize, int totalPackets, ref int sentPackets, int interval, CancellationToken cancellationToken)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();
            byte[] packet = new byte[packetSize];

            for (int i = 0; i < fileData.Length && !cancellationToken.IsCancellationRequested; i += packetSize)
            {
                int currentPacketSize = Math.Min(packetSize, fileData.Length - i);

                try
                {
                    if (currentPacketSize == packetSize)
                    {
                        Buffer.BlockCopy(fileData, i, packet, 0, currentPacketSize);
                        udpSender.Send(packet, currentPacketSize);
                    }
                    else
                    {
                        byte[] lastPacket = new byte[currentPacketSize];
                        Buffer.BlockCopy(fileData, i, lastPacket, 0, currentPacketSize);
                        udpSender.Send(lastPacket, currentPacketSize);
                    }

                    sentPackets++;
                    sendCount++;
                    Interlocked.Increment(ref totalSentPackets);
                }
                catch (Exception ex)
                {
                    AppendLogThreadSafeAsync($"[发送失败] 包 {sentPackets}: {ex.Message}", Color.Red);
                    continue;
                }

                if (sentPackets % 100 == 0 || sentPackets == totalPackets)
                {
                    UpdateSendCountLabel();
                    UpdateProgressThreadSafe(sentPackets, totalPackets);

                    if (sentPackets % 1000 == 0 || sentPackets == totalPackets)
                    {
                        double elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
                        double mbps = (sentPackets * packetSize / 1024.0 / 1024.0) / elapsedSeconds;

                        AppendLogThreadSafe(
                            $"[限速发送] 已发送 {sentPackets}/{totalPackets} 包 " +
                            $"({(double)sentPackets / totalPackets * 100:F1}%) | 速度: {mbps:F1} MB/s",
                            Color.DarkCyan);
                    }
                }

                if (interval > 0)
                {
                    Thread.Sleep(interval);
                }
            }
        }

        private void UpdateProgressThreadSafe(int current, int total)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<int, int>(UpdateProgressThreadSafe), current, total);
                return;
            }

            if (total > 0)
            {
                int percentage = (int)((double)current / total * 100);
                progressBarFileSend.Value = Math.Min(percentage, 100);
                lblSendProgress.Text = $"发送进度: {percentage}% ({current}/{total})";
            }
        }

        #endregion

        #region 初始化和基础方法

        private void InitEvent()
        {
            btnSend.Click += BtnSend_Click;
            btnStartListen.Click += BtnStartListen_Click;
            btnStopListen.Click += BtnStopListen_Click;
            btnSendProtocol.Click += BtnSendProtocol_Click;

            chkEnableParsing.CheckedChanged += ChkEnableParsing_CheckedChanged;
            btnClearParsedData.Click += BtnClearParsedData_Click;

            btnBrowseFile.Click += BtnBrowseFile_Click;
            btnStartFileSend.Click += BtnStartFileSend_Click;
            btnStopFileSend.Click += BtnStopFileSend_Click;

            chkCh1.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh2.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh3.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh4.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh5.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh6.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh7.Click += (s, e) => UpdateChannelMaskLabel();
            chkCh8.Click += (s, e) => UpdateChannelMaskLabel();

            btnApplyChannels.Click += (s, e) =>
            {
                try
                {
                    byte mask = BuildChannelMaskFromUI();
                    Send_ChannelMask_Then_Start(mask);
                }
                catch (Exception ex)
                {
                    AppendLogThreadSafe("[一键配置错误] " + ex.Message, Color.Red);
                }
            };
        }

        private void BtnSend_Click(object sender, EventArgs e)
        {
            try
            {
                string ip = txtSendIP.Text.Trim();
                int port = int.Parse(txtSendPort.Text.Trim());
                byte[] userBytes = HexStringToBytes(txtSendContent.Text.Trim());

                byte[] payload;
                if (cbAppendCRC.Checked)
                {
                    uint crc = CRC32.Compute(userBytes);
                    byte[] crcBytes = BitConverter.GetBytes(crc);
                    payload = new byte[userBytes.Length + 4];
                    Buffer.BlockCopy(userBytes, 0, payload, 0, userBytes.Length);
                    Buffer.BlockCopy(crcBytes, 0, payload, userBytes.Length, 4);

                    AppendLogThreadSafe($"[发送原始+CRC] → {ip}:{port} - {BytesToHexString(userBytes)} + CRC32={BytesToHexString(crcBytes)}", Color.Blue);
                }
                else
                {
                    payload = userBytes;
                    AppendLogThreadSafe($"[发送原始] → {ip}:{port} - {BytesToHexString(payload)}", Color.Blue);
                }

                using (var senderUdp = new UdpClient())
                    senderUdp.Send(payload, payload.Length, ip, port);

                sendCount++;
                UpdateSendCountLabel();
            }
            catch (Exception ex)
            {
                AppendLogThreadSafe("[发送错误] " + ex.Message, Color.Red);
            }
        }

        private void BtnSendProtocol_Click(object sender, EventArgs e)
        {
            try
            {
                string ip = txtSendIP.Text.Trim();
                int port = int.Parse(txtSendPort.Text.Trim());

                byte regAddr = 0x00;
                uint dataVal = 0;

                switch (cmbRegister.SelectedIndex)
                {
                    case 0:
                        regAddr = 0x01;
                        byte mask = BuildChannelMaskFromUI();
                        dataVal = mask;
                        break;
                    case 1:
                        regAddr = 0x00;
                        dataVal = ParseUint(txtDataValue.Text.Trim());
                        break;
                    case 2:
                        regAddr = 0x02;
                        dataVal = 0;
                        break;
                    case 3:
                        regAddr = 0x03;
                        dataVal = ParseVoltageToUint(txtDataValue.Text.Trim());
                        break;
                    case 4:
                        regAddr = 0x04;
                        dataVal = ParseVoltageToUint(txtDataValue.Text.Trim());
                        break;
                    case 5:
                        regAddr = 0x05;
                        dataVal = ParseVoltageToUint(txtDataValue.Text.Trim());
                        break;
                    case 6:
                        regAddr = 0x06;
                        dataVal = ParseUint(txtDataValue.Text.Trim());
                        break;
                    default:
                        throw new InvalidOperationException("请选择有效的寄存器");
                }

                byte[] frame = MakeFrame(regAddr, dataVal);

                using (var senderUdp = new UdpClient())
                    senderUdp.Send(frame, frame.Length, ip, port);

                string regName = cmbRegister.SelectedItem?.ToString() ?? $"0x{regAddr:X2}";
                AppendLogThreadSafe($"[发送协议帧] → {ip}:{port} - {regName}, DATA=0x{dataVal:X8}, RAW={BytesToHexString(frame)}", Color.DarkCyan);

                sendCount++;
                UpdateSendCountLabel();
            }
            catch (Exception ex)
            {
                AppendLogThreadSafe("[协议帧发送错误] " + ex.Message, Color.Red);
            }
        }

        private uint ParseVoltageToUint(string voltageText)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(voltageText))
                    return 0;

                if (voltageText.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                {
                    return Convert.ToUInt32(voltageText, 16);
                }

                if (double.TryParse(voltageText, out double voltage))
                {
                    uint voltageUint = (uint)Math.Round(Math.Abs(voltage) * 10000);
                    return voltageUint;
                }

                return Convert.ToUInt32(voltageText, 10);
            }
            catch
            {
                throw new FormatException($"无法解析电压值: {voltageText}，请输入有效的数值（如 1.2345）或十六进制值（如 0x1234）");
            }
        }

        private void Send_ChannelMask_Then_Start(byte channelMask)
        {
            string ip = txtSendIP.Text.Trim();
            int port = int.Parse(txtSendPort.Text.Trim());

            byte[] frameCh = MakeFrame(0x01, channelMask);
            byte[] frameStart = MakeFrame(0x00, 0u);

            using (var senderUdp = new UdpClient())
            {
                senderUdp.Send(frameCh, frameCh.Length, ip, port);
                AppendLogThreadSafe($"[发送协议帧] → {ip}:{port} - {BytesToHexString(frameCh)}", Color.Blue);

                Thread.Sleep(20);
                senderUdp.Send(frameStart, frameStart.Length, ip, port);
                AppendLogThreadSafe($"[发送协议帧] → {ip}:{port} - {BytesToHexString(frameStart)}", Color.Blue);
            }

            sendCount += 2;
            UpdateSendCountLabel();
        }

        private static byte[] MakeFrame(byte regAddr, uint data)
        {
            return new byte[]
            {
               0x55, 0xA5,
               regAddr,
               (byte)((data >> 24) & 0xFF),
               (byte)((data >> 16) & 0xFF),
               (byte)((data >>  8) & 0xFF),
               (byte)((data >>  0) & 0xFF),
               0xF0
            };
        }

        private static uint ParseUint(string text)
        {
            if (string.IsNullOrEmpty(text)) return 0;
            if (text.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                return Convert.ToUInt32(text, 16);
            return Convert.ToUInt32(text, 10);
        }

        private byte[] HexStringToBytes(string hex)
        {
            hex = hex.Replace(" ", "");
            if (hex.Length % 2 != 0)
                throw new FormatException("十六进制字符串长度必须为偶数");
            var bytes = new byte[hex.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
                bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            return bytes;
        }

        private string BytesToHexString(byte[] bytes)
        {
            var sb = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                sb.AppendFormat("{0:X2}", bytes[i]);
                if (i < bytes.Length - 1) sb.Append(" ");
            }
            return sb.ToString();
        }

        private void AppendLogThreadSafe(string text, Color color = default)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.BeginInvoke(new Action(() => AppendLogThreadSafe(text, color)));
                return;
            }
            int start = txtLog.TextLength;
            txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss") + " " + text + "\r\n");
            int end = txtLog.TextLength;
            txtLog.Select(start, end - start);
            txtLog.SelectionColor = color == default ? Color.Black : color;
            txtLog.SelectionLength = 0;
            txtLog.ScrollToCaret();
        }

        private void UpdateSendCountLabel()
        {
            if (lblSendCount.InvokeRequired)
            {
                lblSendCount.BeginInvoke(new Action(UpdateSendCountLabel));
                return;
            }
            lblSendCount.Text = $"发送条数: {sendCount}";
        }

        private byte BuildChannelMaskFromUI()
        {
            int mask = 0;
            if (chkCh1.Checked) mask |= (1 << 0);
            if (chkCh2.Checked) mask |= (1 << 1);
            if (chkCh3.Checked) mask |= (1 << 2);
            if (chkCh4.Checked) mask |= (1 << 3);
            if (chkCh5.Checked) mask |= (1 << 4);
            if (chkCh6.Checked) mask |= (1 << 5);
            if (chkCh7.Checked) mask |= (1 << 6);
            if (chkCh8.Checked) mask |= (1 << 7);
            return (byte)mask;
        }

        private void UpdateChannelMaskLabel()
        {
            byte mask = BuildChannelMaskFromUI();
            lblChannelMask.Text = $"当前掩码：0x{mask:X2}（十进制 {mask}）";
        }

        #endregion
    }

    // 优化的数据包结构
    public struct UdpPacket
    {
        public byte[] Data;
        public int DataLength;
        public IPEndPoint RemoteEndPoint;
        public DateTime Timestamp;
    }

    public struct VoltagePoint
    {
        public DateTime Timestamp { get; set; }
        public double Voltage { get; set; }
        public int SampleIndex { get; set; }
        public string Source { get; set; }

        public VoltagePoint(DateTime timestamp, double voltage, int sampleIndex, string source)
        {
            Timestamp = timestamp;
            Voltage = voltage;
            SampleIndex = sampleIndex;
            Source = source;
        }
    }
}
